using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework.Content;
using System.Xml;
using System.IO;
using RoboTrocity.Code.ObjectStates;
using RoboTrocity.Code.Props;

// Contains all the information about objects as well as triggers
namespace RoboTrocity {
    class Map {
        ObjectList objectList; //everything
        ObjectList movableList; //only for movable objects
    	//ObjectList terrainList; //only for terrain -> doesn't need to be updated
        //also add Trigger list here

        public Map() {
            objectList = new ObjectList();
            movableList = new ObjectList();
		}

        public void addObject(GameObject gObject) {
            objectList.add(gObject);
			
            if (gObject is MovableObject) {
                movableList.add((MovableObject)gObject);
            }
        }

		public void addObject(GameObject[] gObjectList) {
			for (int i = 0; i < gObjectList.Length; i++) {
				addObject(gObjectList[i]);
			}
		}

		public void addObject(List<GameObject> gObjectList) {
			for (int i = 0; i < gObjectList.Count; i++) {
				addObject(gObjectList[i]);
			}
		}

		public void removeObject(GameObject gObject) {
			objectList.remove(gObject);
			if (gObject is MovableObject) {
				movableList.remove((GameObject)gObject);
			}
		}

        public void Update(float elapsed) {
			for (int i=0; i< movableList.ObjectArray.Count; i++){
                MovableObject mObject = (MovableObject)movableList.ObjectArray[i];
                //this will be optimized later, when needed
                for (int j = 0; j < objectList.ObjectArray.Count; j++) {
                	GameObject gObject = objectList.ObjectArray[j];
                    if (gObject != mObject) {
						if (gObject.Bounds.IntersectsWith(mObject.Bounds)){
							mObject.collideWith(gObject);
							gObject.collideWith(mObject);
						}
                    }
                }
				mObject.Update(elapsed);
				if (mObject.CurrentState is DeleteState){
					//delete it from the list
					objectList.remove(mObject);
					movableList.remove(mObject);
				}
            }
            objectList.sort();
        }

		public GameObject getObjectAt(Point center) {
			foreach (GameObject gObject in ObjectList.ObjectArray) {
				if (CollisionHandler.PointAndSquareIntersects(center, gObject.Bounds) && 
					center != gObject.Center) {
					return gObject;
				}
			}
			return null;
		}


		public void loadMap(ContentManager content, String mapName) {
			string mapFile = "./" + mapName + ".xml";
			XmlDocument xmldoc = new XmlDocument();
			xmldoc.Load(mapFile);

			XmlNodeList nodeList = xmldoc.SelectNodes("RoboMap/TerrainObjects/Terrain");
			foreach (XmlNode terrainNode in nodeList) {
				Terrain t = new Terrain(getPositionFromXML(terrainNode), getTextureNameFromXML(terrainNode));
				this.addObject(t); 
			} 
			nodeList = xmldoc.SelectNodes("RoboMap/TerrainSlopes/Slope");
			/*foreach (XmlNode slopeNode in nodeList) {
				TerrainSlope slope = new TerrainSlope(float.Parse(slopeNode.SelectSingleNode("Slope").Attributes.GetNamedItem("value").Value));
				slope.Position = getPositionFromXML(slopeNode);
				slope.DispSprite = new Sprite(getTextureNameFromXML(slopeNode));
				this.addObject(slope);
			}*/
		}

		private Point getPositionFromXML(XmlNode objectNode) {
			XmlNode positionNode = objectNode.SelectSingleNode("Position");
			return new Point(int.Parse(positionNode.Attributes.GetNamedItem("locX").Value),
											int.Parse(positionNode.Attributes.GetNamedItem("locY").Value));
			
		}

		private string getTextureNameFromXML(XmlNode objectNode) {
			return objectNode.SelectSingleNode("Texture").Attributes.GetNamedItem("name").Value;
		}


		public ObjectList ObjectList {
			get { return objectList; }
			set { objectList = value; }
		}

		public static void saveMap(Map gameMap) {
			String entityData = "", terrainData = "", slopeData = "";
			foreach (GameObject gObject in gameMap.ObjectList.ObjectArray) {
				if (gObject is TerrainSlope) {
					slopeData += ((TerrainSlope)gObject).MapXMLData;
				} else if (gObject is Terrain) {
					terrainData += ((Terrain)gObject).MapXMLData;
				}
			}

			String stringXML = "";
			stringXML += "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<RoboMap>\n"
				+ "<Player>\n<Position locX=\"10\" locY=\"10\" />\n</Player>\n<Entities>\n";
			//entities
			stringXML += "</Entities>\n<TerrainObjects>\n";
			stringXML += terrainData; //terrain
			stringXML += "</TerrainObjects>\n<TerrainSlopes>\n";
			stringXML += slopeData; //slopes
			stringXML += "</TerrainSlopes>\n</RoboMap>\n";

			//save into file
			string mapLoc = "C:\\Users\\Nicholas\\Documents\\Visual Studio 2008\\Projects\\RoboTrocity\\map.xml";

			// create a writer and open the file
			TextWriter tw = new StreamWriter(mapLoc);

			// write a line of text to the file
			tw.WriteLine(stringXML);

			// close the stream
			tw.Close();
		}

    }
}
